/**
 * EditorErrorList.js
 * Provides a UI component to display and navigate to editor errors
 */

/**
 * Creates and manages the error list component
 * @param {Object} monaco - The Monaco instance
 * @param {Object} editor - The Monaco editor instance
 * @param {Function} customChatRunner - Function to handle fix requests
 * @returns {Object} Error list API for controlling the list
 */
export function setupErrorList(monaco, editor, customChatRunner) {
  let errorListContainer = null;
  let isCollapsed = false;
  let currentModel = null;
  let editorWrapperObserver = null;

  // Save error list height to localStorage
  function saveErrorListHeight(height) {
    try {
      localStorage.setItem("aiChatJPT_errorListHeight", height);
    } catch (e) {
      console.warn("Failed to save error list height to localStorage", e);
    }
  }

  // Load error list height from localStorage
  function loadErrorListHeight() {
    try {
      const savedHeight = localStorage.getItem("aiChatJPT_errorListHeight");
      return savedHeight ? parseInt(savedHeight, 10) : 180; // Default height is 180px
    } catch (e) {
      console.warn("Failed to load error list height from localStorage", e);
      return 180; // Default height
    }
  }

  // Create the error list container
  function createErrorList() {
    // If already exists, return it
    if (errorListContainer) {
      return errorListContainer;
    }

    // Initialize filter state
    let filterType = "all"; // 'all', 'error', 'warning', 'info'

    errorListContainer = document.createElement("div");
    errorListContainer.className = "error-list-container";

    // Set the initial height from localStorage
    const initialHeight = loadErrorListHeight();
    errorListContainer.style.height = `${initialHeight}px`;

    // Create resizer handle
    const resizeHandle = document.createElement("div");
    resizeHandle.className = "error-list-resizer";

    // Create header
    const header = document.createElement("div");
    header.className = "error-list-header";

    const title = document.createElement("div");
    title.className = "error-list-title";
    title.textContent = "问题";

    const errorCount = document.createElement("span");
    errorCount.className = "error-count";
    errorCount.textContent = "0";
    title.appendChild(errorCount);

    // Create filter button
    const filterBtn = document.createElement("div");
    filterBtn.className = "error-list-filter";
    filterBtn.title = "筛选问题类型";
    filterBtn.innerHTML = '<div class="error-filter-icon"></div>';

    // Create filter menu
    const filterMenu = document.createElement("div");
    filterMenu.className = "error-filter-menu";
    filterMenu.style.display = "none";

    // Filter options
    const filterOptions = [
      { id: "all", text: "显示所有问题", icon: "filter-all" },
      { id: "error", text: "仅显示错误", icon: "filter-error" },
      { id: "warning", text: "仅显示警告", icon: "filter-warning" },
      { id: "info", text: "仅显示信息", icon: "filter-info" },
    ];

    filterOptions.forEach((option) => {
      const filterOption = document.createElement("div");
      filterOption.className = "error-filter-option";
      filterOption.dataset.filter = option.id;

      const optionIcon = document.createElement("span");
      optionIcon.className = `error-filter-option-icon ${option.icon}`;

      const optionText = document.createElement("span");
      optionText.textContent = option.text;

      // Checkmark
      const checkmark = document.createElement("span");
      checkmark.className = "error-filter-checkmark";
      checkmark.style.display =
        option.id === filterType ? "inline-block" : "none";

      filterOption.appendChild(optionIcon);
      filterOption.appendChild(optionText);
      filterOption.appendChild(checkmark);

      // Add click event
      filterOption.addEventListener("click", () => {
        // Update all option checkmarks
        filterMenu.querySelectorAll(".error-filter-checkmark").forEach((el) => {
          el.style.display = "none";
        });
        checkmark.style.display = "inline-block";

        // Update filter state
        filterType = option.id;

        // Apply filter and close menu
        updateErrorList();
        filterMenu.style.display = "none";
      });

      filterMenu.appendChild(filterOption);
    });

    // Add filter button click event
    filterBtn.addEventListener("click", (e) => {
      e.stopPropagation();
      const isVisible = filterMenu.style.display === "block";
      filterMenu.style.display = isVisible ? "none" : "block";

      // Click outside to close menu
      if (!isVisible) {
        const clickOutside = (e) => {
          if (!filterMenu.contains(e.target) && !filterBtn.contains(e.target)) {
            filterMenu.style.display = "none";
            document.removeEventListener("click", clickOutside);
          }
        };
        setTimeout(() => {
          document.addEventListener("click", clickOutside);
        }, 0);
      }
    });

    // Create Fix All button
    const fixAllBtn = document.createElement("div");
    fixAllBtn.className = "error-fix-all";
    fixAllBtn.title = "一键修复所有问题";
    fixAllBtn.innerHTML =
      '<div class="error-fix-all-icon"></div><span>吉PT一键修复</span>';

    // Add click event for Fix All button
    fixAllBtn.addEventListener("click", () => {
      // Get all markers from current model
      if (!editor || !monaco) return;

      const model = editor.getModel();
      if (!model) return;

      // Get all markers
      let markers = monaco.editor.getModelMarkers({ resource: model.uri });

      if (markers.length === 0) {
        // No errors to fix
        return;
      }

      // Select all code in the current file
      const lastLineNumber = model.getLineCount();
      const lastLineLength = model.getLineMaxColumn(lastLineNumber);

      editor.setSelection({
        startLineNumber: 1,
        startColumn: 1,
        endLineNumber: lastLineNumber,
        endColumn: lastLineLength,
      });

      // Focus the editor so the selection is visible
      editor.focus();

      // Collect all error messages
      const errorMessages = markers
        .map((marker) => {
          return `- [行 ${marker.startLineNumber}, 列 ${marker.startColumn}]: ${marker.message}`;
        })
        .join("\n");

      // Get the full file code
      const fileContent = model.getValue();

      // Create the prompt
      const prompt = `请帮我全部修复，最后直接给出修复好的完整的JavaScript代码，以下是代码的错误信息：\n\n${errorMessages}`;

      // Send to AI for fixing
      customChatRunner(90, prompt);
    });

    const toggle = document.createElement("div");
    toggle.className = "error-list-toggle";

    const toggleIcon = document.createElement("div");
    toggleIcon.className = "error-list-toggle-icon";
    toggle.appendChild(toggleIcon);

    // Create content area
    const content = document.createElement("div");
    content.className = "error-list-content";

    const table = document.createElement("table");
    table.className = "error-list-table";
    content.appendChild(table);

    // Add event listeners
    toggle.addEventListener("click", () => {
      isCollapsed = !isCollapsed;
      if (isCollapsed) {
        // Save current height for restoration
        const currentHeight = parseInt(
          document.defaultView.getComputedStyle(errorListContainer).height,
          10
        );
        errorListContainer.dataset.prevHeight = currentHeight;

        // Apply minimized style
        errorListContainer.classList.add("collapsed");
        toggleIcon.classList.add("collapsed");
        errorListContainer.style.height = `${header.offsetHeight}px`;
        content.style.display = "none";
        resizeHandle.style.display = "none";
      } else {
        // Restore previous height
        const prevHeight =
          errorListContainer.dataset.prevHeight || loadErrorListHeight();
        errorListContainer.style.height = `${prevHeight}px`;

        // Remove minimized style
        errorListContainer.classList.remove("collapsed");
        toggleIcon.classList.remove("collapsed");
        content.style.display = "block";
        resizeHandle.style.display = "block";

        // Update content area height
        content.style.maxHeight = `${prevHeight - header.offsetHeight}px`;
      }
    });

    // Implement resize functionality - Optimize drag performance
    let startY = 0;
    let startHeight = 0;

    function onMouseDown(e) {
      // Prevent event bubbling and default behavior
      e.stopPropagation();
      e.preventDefault();

      startY = e.clientY;
      startHeight = parseInt(
        document.defaultView.getComputedStyle(errorListContainer).height,
        10
      );

      // Use requestAnimationFrame for smooth drag
      document.documentElement.addEventListener("mousemove", onMouseMove, {
        passive: true,
      });
      document.documentElement.addEventListener("mouseup", onMouseUp);
      document.body.style.cursor = "ns-resize";
      resizeHandle.classList.add("active");

      // Add styles to list container, remove transition effect to improve drag responsiveness
      errorListContainer.classList.add("resizing");
    }

    function onMouseMove(e) {
      // Use requestAnimationFrame to reduce redraw frequency, improve performance
      requestAnimationFrame(() => {
        const newHeight = startHeight - (e.clientY - startY);
        if (newHeight > 50 && newHeight < window.innerHeight * 0.8) {
          errorListContainer.style.height = `${newHeight}px`;
          // Update content area height
          content.style.maxHeight = `${newHeight - header.offsetHeight}px`;
        }
      });
    }

    function onMouseUp() {
      document.documentElement.removeEventListener("mousemove", onMouseMove);
      document.documentElement.removeEventListener("mouseup", onMouseUp);
      document.body.style.cursor = "";
      resizeHandle.classList.remove("active");

      // Remove drag styles
      errorListContainer.classList.remove("resizing");

      // Save current height to localStorage
      const currentHeight = parseInt(
        document.defaultView.getComputedStyle(errorListContainer).height,
        10
      );
      saveErrorListHeight(currentHeight);

      // If minimized, don't show content area
      if (isCollapsed) {
        content.style.display = "none";
      }
    }

    resizeHandle.addEventListener("mousedown", onMouseDown);

    // Append elements
    header.appendChild(title);
    header.appendChild(fixAllBtn);
    header.appendChild(filterBtn);
    header.appendChild(filterMenu);
    header.appendChild(toggle);

    errorListContainer.appendChild(resizeHandle);
    errorListContainer.appendChild(header);
    errorListContainer.appendChild(content);

    // Filter method - Filter list based on type
    errorListContainer.filterMarkers = function (markers) {
      if (!markers || markers.length === 0) return markers;

      // 如果筛选类型是 "all"，返回所有标记
      if (filterType === "all") return markers;

      // 根据筛选类型筛选标记
      return markers.filter((marker) => {
        switch (filterType) {
          case "error":
            return marker.severity === monaco.MarkerSeverity.Error;
          case "warning":
            return marker.severity === monaco.MarkerSeverity.Warning;
          case "info":
            return (
              marker.severity === monaco.MarkerSeverity.Info ||
              marker.severity === monaco.MarkerSeverity.Hint
            );
          default:
            return true;
        }
      });
    };

    // Add filter CSS styles
    const styleId = "error-filter-styles";
    if (!document.getElementById(styleId)) {
      const style = document.createElement("style");
      style.id = styleId;
      style.innerHTML = `
        .error-filter-menu {
          position: absolute;
          top: 40px;
          right: 10px;
          background-color: rgb(45, 45, 45);
          border: 1px solid rgba(100, 100, 100, 0.3);
          border-radius: 6px;
          padding: 5px 0;
          width: 180px;
          z-index: 1000;
          box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3);
        }
        
        .error-filter-option {
          padding: 8px 12px;
          cursor: pointer;
          display: flex;
          align-items: center;
          transition: background-color 0.2s;
        }
        
        .error-filter-option:hover {
          background-color: rgba(77, 138, 240, 0.2);
        }
        
        .error-filter-option-icon {
          width: 14px;
          height: 14px;
          margin-right: 8px;
          display: inline-block;
        }
        
        .error-filter-icon {
          width: 18px;
          height: 18px;
          background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolygon points='22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3'%3E%3C/polygon%3E%3C/svg%3E");
          background-repeat: no-repeat;
          background-position: center;
          opacity: 0.7;
        }
        
        .error-filter-checkmark {
          margin-left: auto;
          width: 18px;
          height: 18px;
          background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%234d8af0' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E");
          background-repeat: no-repeat;
          background-position: center;
        }
        
        .filter-all {
          background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23aaa' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='16' x2='12' y2='12'%3E%3C/line%3E%3Cline x1='12' y1='8' x2='12' y2='8'%3E%3C/line%3E%3C/svg%3E");
        }
        
        .filter-error {
          background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ff6347' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='15' y1='9' x2='9' y2='15'%3E%3C/line%3E%3Cline x1='9' y1='9' x2='15' y2='15'%3E%3C/line%3E%3C/svg%3E");
        }
        
        .filter-warning {
          background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffa500' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z'%3E%3C/path%3E%3Cline x1='12' y1='9' x2='12' y2='13'%3E%3C/line%3E%3Cline x1='12' y1='17' x2='12' y2='17'%3E%3C/line%3E%3C/svg%3E");
        }
        
        .filter-info {
          background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%233498db' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='16' x2='12' y2='12'%3E%3C/line%3E%3Cline x1='12' y1='8' x2='12' y2='8'%3E%3C/line%3E%3C/svg%3E");
        }
        
        .error-list-filter.active .error-filter-icon {
          opacity: 1;
          filter: drop-shadow(0 0 2px rgba(77, 138, 240, 0.6));
        }
      `;
      document.head.appendChild(style);
    }

    // Add filter menu to container
    errorListContainer.appendChild(filterMenu);

    // Find the script editor wrapper and append the error list to it
    appendToEditorWrapper();

    return errorListContainer;
  }

  // Function to find and append to editor wrapper
  function appendToEditorWrapper() {
    if (!errorListContainer) return;

    // First try to find the code editor container
    const codeEditorContainer = document.querySelector(
      ".script-editor_codeEditorContainer__0WYgN"
    );

    // Setup debug panel observer
    function setupDebugPanelObserver(parentElement) {
      // Check if debug panel exists
      const debugPanel = document.querySelector(
        ".script-editor_debugPanel__b3m_6"
      );

      // Position the error list above the debug panel if it exists
      if (debugPanel) {
        const debugPanelHeight = debugPanel.offsetHeight;
        errorListContainer.style.bottom = `${debugPanelHeight}px`;

        // Set up observer to watch for changes in the debug panel height/visibility
        const debugPanelObserver = new MutationObserver(() => {
          const updatedDebugPanel = document.querySelector(
            ".script-editor_debugPanel__b3m_6"
          );
          if (updatedDebugPanel) {
            const updatedHeight = updatedDebugPanel.offsetHeight;
            const display = window.getComputedStyle(updatedDebugPanel).display;

            // Update position based on debug panel visibility and height
            if (display === "none") {
              errorListContainer.style.bottom = "0";
            } else {
              errorListContainer.style.bottom = `${updatedHeight}px`;
            }
          } else {
            errorListContainer.style.bottom = "0";
          }
        });

        // Observe changes to the debug panel and parent element
        debugPanelObserver.observe(parentElement, {
          childList: true,
          subtree: true,
          attributes: true,
          attributeFilter: ["style", "class"],
        });

        return debugPanelObserver;
      }

      return null;
    }

    // If we found the code editor container, append after it
    if (codeEditorContainer && codeEditorContainer.parentNode) {
      const parentElement = codeEditorContainer.parentNode;

      // Set position to relative on the parent if not already set
      if (getComputedStyle(parentElement).position === "static") {
        parentElement.style.position = "relative";
      }

      // Position at bottom of the parent, not inside the code editor
      errorListContainer.style.position = "absolute";
      errorListContainer.style.bottom = "0";
      errorListContainer.style.left = "0";
      errorListContainer.style.right = "0";

      // Setup debug panel observer
      setupDebugPanelObserver(parentElement);

      // Insert error list into the parent, after the code editor container
      if (errorListContainer.parentNode !== parentElement) {
        parentElement.appendChild(errorListContainer);
      }

      // Stop observing if we were looking for the wrapper
      if (editorWrapperObserver) {
        editorWrapperObserver.disconnect();
        editorWrapperObserver = null;
      }

      return;
    }

    // Fallback to script editor wrapper if code editor container is not found
    const scriptEditorWrapper = document.querySelector(
      ".script-editor_scriptEditorWrapper__zjjus"
    );

    if (scriptEditorWrapper) {
      // Set position to relative on the script editor wrapper if not already set
      if (getComputedStyle(scriptEditorWrapper).position === "static") {
        scriptEditorWrapper.style.position = "relative";
      }

      // Position at bottom
      errorListContainer.style.position = "absolute";
      errorListContainer.style.bottom = "0";

      // Setup debug panel observer
      setupDebugPanelObserver(scriptEditorWrapper);

      scriptEditorWrapper.appendChild(errorListContainer);

      // Stop observing if we were looking for the wrapper
      if (editorWrapperObserver) {
        editorWrapperObserver.disconnect();
        editorWrapperObserver = null;
      }
    } else {
      // If wrapper not found yet, start observing for it
      if (!editorWrapperObserver) {
        console.warn("Script editor wrapper not found, setting up observer");

        // Add to body temporarily
        document.body.appendChild(errorListContainer);

        // Set up mutation observer to detect when the editor wrapper is added
        editorWrapperObserver = new MutationObserver((mutations) => {
          const codeContainer = document.querySelector(
            ".script-editor_codeEditorContainer__0WYgN"
          );

          if (codeContainer && codeContainer.parentNode) {
            // Found the code editor container
            if (errorListContainer.parentNode === document.body) {
              document.body.removeChild(errorListContainer);
            }
            appendToEditorWrapper();
            return;
          }

          const wrapper = document.querySelector(
            ".script-editor_scriptEditorWrapper__zjjus"
          );
          if (wrapper) {
            // Move the error list from body to the wrapper
            if (errorListContainer.parentNode === document.body) {
              document.body.removeChild(errorListContainer);
            }
            appendToEditorWrapper();
          }
        });

        // Start observing
        editorWrapperObserver.observe(document.body, {
          childList: true,
          subtree: true,
        });
      }
    }
  }

  // Update the error list with current model markers
  function updateErrorList() {
    if (!editor || !monaco) return;

    const container = createErrorList();
    const model = editor.getModel();

    if (!model) return;

    // Store current model for tracking changes
    currentModel = model;

    // Get markers (errors, warnings, etc.)
    let markers = monaco.editor.getModelMarkers({ resource: model.uri });
    const originalCount = markers.length;

    // Update Fix All button visibility based on errors
    const fixAllBtn = container.querySelector(".error-fix-all");
    if (fixAllBtn) {
      fixAllBtn.style.display = markers.length > 0 ? "flex" : "none";
    }

    // 应用筛选器过滤标记
    if (container.filterMarkers) {
      markers = container.filterMarkers(markers);
    }

    // 更新筛选按钮状态
    const filterBtn = container.querySelector(".error-list-filter");
    if (filterBtn) {
      // 获取当前选中的筛选类型
      const filterMenu = container.querySelector(".error-filter-menu");
      const selectedFilter = filterMenu
        ? filterMenu.querySelector(
            ".error-filter-checkmark[style*='inline-block']"
          )?.parentElement?.dataset?.filter
        : "all";

      // 如果不是"all"或者筛选后数量减少，显示筛选状态
      if (selectedFilter !== "all" || markers.length < originalCount) {
        filterBtn.classList.add("active");
        filterBtn.title = `筛选问题类型: ${
          selectedFilter === "all"
            ? "全部"
            : selectedFilter === "error"
            ? "错误"
            : selectedFilter === "warning"
            ? "警告"
            : "信息"
        }`;
      } else {
        filterBtn.classList.remove("active");
        filterBtn.title = "筛选问题类型";
      }
    }

    // Count different types of messages
    const errorCount = markers.filter(
      (marker) => marker.severity === monaco.MarkerSeverity.Error
    ).length;
    const warningCount = markers.filter(
      (marker) => marker.severity === monaco.MarkerSeverity.Warning
    ).length;
    const infoCount = markers.filter(
      (marker) => marker.severity === monaco.MarkerSeverity.Info
    ).length;
    const noticeCount = markers.filter((marker) =>
      marker.message.includes("注意")
    ).length;

    // Determine badge color based on message types present
    const countBadge = container.querySelector(".error-count");
    countBadge.textContent = markers.length.toString();

    // Clear existing classes
    countBadge.classList.remove("error-count-notice", "error-count-info");

    // Set appropriate class based on marker types
    if (infoCount > 0 && errorCount === 0 && warningCount === 0) {
      // If only info messages, use info style
      countBadge.classList.add("error-count-info");
    } else if (noticeCount > 0 && errorCount === 0) {
      // If notice warnings but no errors, use notice style
      countBadge.classList.add("error-count-notice");
    }
    // Default is error style (no class needed)

    // Get table element
    const table = container.querySelector(".error-list-table");
    table.innerHTML = "";

    // Create table content
    markers.forEach((marker) => {
      const row = document.createElement("tr");
      row.className = "error-list-item";

      // Severity cell
      const sevCell = document.createElement("td");
      const sevIcon = document.createElement("span");
      sevIcon.className = "error-icon";

      // Set appropriate icon based on severity
      switch (marker.severity) {
        case monaco.MarkerSeverity.Error:
          sevIcon.classList.add("error-icon-error");
          row.classList.add("error-list-item-error");
          break;
        case monaco.MarkerSeverity.Warning:
          sevIcon.classList.add("error-icon-warning");
          row.classList.add("error-list-item-warning");
          break;
        default:
          sevIcon.classList.add("error-icon-info");
          row.classList.add("error-list-item-info");
      }

      sevCell.appendChild(sevIcon);

      // Message cell
      const msgCell = document.createElement("td");
      msgCell.className = "error-message";

      // Set cell class based on severity
      switch (marker.severity) {
        case monaco.MarkerSeverity.Error:
          msgCell.classList.add("error-message-error");
          break;
        case monaco.MarkerSeverity.Warning:
          // Check if the message contains "注意" and apply a special class
          if (marker.message.includes("注意")) {
            msgCell.classList.add("error-message-notice");
          } else {
            msgCell.classList.add("error-message-warning");
          }
          break;
        case monaco.MarkerSeverity.Info:
          msgCell.classList.add("error-message-info");
          break;
        default:
          // Default case - no additional class
          break;
      }

      msgCell.textContent = marker.message;

      // Location cell
      const locCell = document.createElement("td");
      locCell.className = "error-location";
      locCell.textContent = `[行 ${marker.startLineNumber}, 列 ${marker.startColumn}]`;

      // Action cell (contains fix button)
      const actionCell = document.createElement("td");
      actionCell.className = "error-actions";

      // Fix button
      const fixButton = document.createElement("button");
      fixButton.className = "error-fix-button";
      fixButton.textContent = "";
      fixButton.addEventListener("click", (e) => {
        e.stopPropagation(); // Prevent row click

        // Get only the specific error line
        const errorLine = model.getLineContent(marker.startLineNumber);

        // Select just the error line in the editor
        editor.setSelection({
          startLineNumber: marker.startLineNumber,
          startColumn: 1,
          endLineNumber: marker.startLineNumber,
          endColumn: model.getLineMaxColumn(marker.startLineNumber),
        });

        // Focus the editor so the selection is visible
        editor.focus();

        // Call custom chat runner to explain the issue with just the specific line
        customChatRunner(
          90,
          `该代码报错："${marker.message}"，请帮我解释一下错误原因，并给出修复建议和完整修复后的JavaScript代码。`
        );
      });

      actionCell.appendChild(fixButton);

      // Add click event to jump to the error location
      row.addEventListener("click", () => {
        // Jump to error position
        editor.revealPositionInCenter({
          lineNumber: marker.startLineNumber,
          column: marker.startColumn,
        });

        // Select the error range
        editor.setSelection({
          startLineNumber: marker.startLineNumber,
          startColumn: marker.startColumn,
          endLineNumber: marker.endLineNumber,
          endColumn: marker.endColumn,
        });

        // Focus the editor
        editor.focus();
      });

      // Append cells to row
      row.appendChild(sevCell);
      row.appendChild(msgCell);
      row.appendChild(locCell);
      row.appendChild(actionCell);

      // Append row to table
      table.appendChild(row);
    });

    // 当没有错误时显示一个友好的消息
    if (markers.length === 0) {
      const emptyRow = document.createElement("tr");
      emptyRow.className = "error-list-empty";

      const emptyCell = document.createElement("td");
      emptyCell.colSpan = 4;
      emptyCell.textContent = "没有问题需要显示";

      emptyRow.appendChild(emptyCell);
      table.appendChild(emptyRow);
    }

    // Show or hide based on markers
    if (
      markers.length > 0 ||
      container.querySelector(".error-list-filter.active")
    ) {
      container.style.display = "flex";
    } else {
      container.style.display = "none";
    }
  }

  // Set up model change listener to update error list
  function setupModelListener() {
    if (!editor || !monaco) return;

    // Update on model changes
    editor.onDidChangeModel(() => {
      updateErrorList();
    });

    // Update when markers change
    monaco.editor.onDidChangeMarkers(() => {
      updateErrorList();
    });

    // Initial update
    updateErrorList();
  }

  // Initialize the error list
  createErrorList();
  setupModelListener();

  // Return API for the error list
  return {
    show: () => {
      if (!errorListContainer) {
        createErrorList();
      }
      errorListContainer.style.display = "flex";
      isCollapsed = false;
      updateErrorList();
    },
    hide: () => {
      if (errorListContainer) {
        errorListContainer.style.display = "none";
      }
    },
    toggle: () => {
      if (!errorListContainer) {
        createErrorList();
        errorListContainer.style.display = "flex";
        isCollapsed = false;
      } else {
        const newDisplay =
          errorListContainer.style.display === "none" ? "flex" : "none";
        errorListContainer.style.display = newDisplay;
        isCollapsed = newDisplay === "none";
      }
      updateErrorList();
    },
    update: updateErrorList,
    dispose: () => {
      if (errorListContainer && errorListContainer.parentNode) {
        errorListContainer.parentNode.removeChild(errorListContainer);
      }
      if (editorWrapperObserver) {
        editorWrapperObserver.disconnect();
      }
    },
  };
}
